#pragma once

#include "noncopyable.h"
#include "Channel.h"
#include "EventLoop.h"
#include "Timestamp.h"

#include <vector>
#include <unordered_map>


/**
*当两个或多个类互相引用对方时，比如 ClassA 引用 ClassB，同时 ClassB 又引用 ClassA。
*在这种情况下，即使包含了对方的头文件，编译器在编译某个类的定义之前可能还没有看到另一个类的完整定义。
*前置声明可以在这种情况下打破循环依赖。
*/
class Channel;
class EventLoop;
//muduo库中多路事件分发器的核心IO复用模块,可以是epoll poll 或者select
//相当于Demultiplex
/**
 * 实际上实现了工厂方法模式，其在父类中提供一个创建对象的接口，
 * 允许子类决定实例化对象的类型。工厂方法模式将对象的实例化推迟到子类中进行，这样的设计使得父类与子类的实现解耦
 * 
 * 抽象产品（Abstract Product）：定义了产品的接口，所有的具体产品都需要实现这个接口。
 * 具体产品（Concrete Product）：实现或继承抽象产品，定义了将被创建的具体产品。
 * 抽象创建者（Abstract Creator）：包含一个或多个工厂方法，这些方法通常返回一个抽象产品类型。
 * 具体创建者（Concrete Creator）：重写或实现抽象创建者中的工厂方法，返回一个具体的产品实例。

 * Poller首先是具体产品，newDefaultPoller 函数是一个静态工厂方法。它根据运行时的情况（例如检查环境变量或其他配置）
 * 来决定返回 Poller 的哪一个具体实现。因此，Poller 也扮演了抽象创建者的角色，因为它提供了创建对象的接口

 * 具体的 Poller 实现（比如 EPollPoller、PollPoller 等）将是具体产品，它们继承自 Poller 并实现其虚函数。

 * newDefaultPoller 函数扮演了具体创建者的角色。它根据运行时的情况（环境变量 MUDUO_USE_POLL）来决定实例化具体的 Poller 类
 */
class Poller : noncopyable
{
public:
    using ChannelList = std::vector<Channel*>;

    Poller(EventLoop* loop);
    virtual ~Poller() = default;
   
    //给所有IO复用保留统一的接口
    //在epoll中相当于启动了epoll_wait
    virtual Timestamp poll(int timeoutMs, ChannelList* activeChannels) = 0;
    virtual void updateChannel(Channel* channel) = 0;
    virtual void removeChannel(Channel* channel) = 0;

    //判断channel是否在当前poller中
    bool hasChannel(Channel* channel) const ;

    //EventLoop可以通过该接口获取默认的IO复用的具体实现
    static Poller* newDefaultPoller(EventLoop* loop);
protected:
    //map的key:sockfd value:sockfd所属的channel通道
    using ChannelMap = std::unordered_map<int, Channel*>;
    ChannelMap channels_;
private:
    EventLoop* ownerLoop_;  //定义Poller所属的事件循环EventLoop
};